package tp6;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import tp6.OpenHashTable.Node;

public class MyMultiMap<K,V> implements Multimap<K,V> {
	private int initSize;
	private int size = 0;
	private double loadFactor;
	private Bucket<K, V>[] buckets;

	@SuppressWarnings("unchecked")
	public MyMultiMap(int initSize, double loadFactor) {
		if (initSize < 0 || loadFactor <= 0) {
			throw new IllegalArgumentException();
		}
		buckets = new Bucket[initSize];
		this.initSize = initSize;
		this.loadFactor = loadFactor;
	}

	@Override
	public List<V> get(K key) {
		Bucket<K, V> node = buckets[key.hashCode() % buckets.length];
		if (node == null) {
			return null;
		}
		return buckets[key.hashCode() % buckets.length].value;
	}

	@Override
	public Set<K> keySet() {
		Set<K> set = new HashSet<K>();
		for (Bucket<K, V> n : buckets) {
			if(n!=null){
				set.add(n.key);
			}
		}
		return set;
	}

	@SuppressWarnings("unchecked")
	private void resize(int newSize) {
		Bucket<K, V>[] newKeys = new Bucket[newSize];
		for (Bucket<K, V> n : buckets) {
			newKeys[n.key.hashCode() % newKeys.length] = buckets[n.key.hashCode()
					% size];
		}
		buckets = newKeys;
	}

	@Override
	public void put(K key, V value) {
		if(key==null){
			throw new IllegalArgumentException();
		}
		
		if (((double) size) / ((double) buckets.length) > loadFactor) {
			resize(initSize * 2);
		}
		buckets[key.hashCode() % buckets.length] = new Bucket<K, V>(key, value, null);
		size++;
	}

	@Override
	public void remove(K key) {
		if(key==null){
			throw new IllegalArgumentException();
		}
		
		buckets[key.hashCode() % size] = null;
		size--;
		if ((double) size/((double) buckets.length) < loadFactor) {
			resize(initSize / 2);
		}
	}

	@Override
	public int size() {
		return size;
	}

	@Override
	public Collection<V> values() {
		Set<V> set=new HashSet<V>();
		for(Bucket<K,V> n:buckets){
			if(n!=null){
				set.add(n.value);
			}
		}		
		return set;
	}

	static class Bucket<S, T> {
		S key;
		T value;
		Bucket<S, T> tail;

		Bucket(S key, T value, Bucket<S, T> tail) {
			this.key = key;
			this.value = value;
			this.tail = tail;
		}

	}

	@Override
	public V getFirst(K key) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void remove(K key, V value) {
		// TODO Auto-generated method stub
		
	}

}
